package java_thinking.unit_21._21_4;

import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @Desc:   4-4 基于监视器模式的线程安全的 车辆追踪案例
 *          1.视图线程与执行更新操作的线程将并发的访问数据模型locations，因此该模型必须是线程安全的
 * @author: cww
 * @DateTime: 2019-06-02 18:40
 */
@ThreadSafe
public class MonitorVehicleTracker {
    /**
     * 车辆位置容器
     * MutablePoint 本身不是线程安全的，但是MonitorVehicleTracker 类是安全的，其包含的 Map对象和 Point对象都
     * 未发布，并且都进行线程锁
     */
    @GuardedBy("this") private final Map<String,MutablePoint> locations;

    public MonitorVehicleTracker(Map<String, MutablePoint> locations) {
        this.locations = deepCopy(locations);
    }

    /**
     * 返回的是拷贝对象，避免 locations 进行逸出
     * 返回的类似于 车辆位置 快照
     * @return
     */
    public synchronized Map<String,MutablePoint> getLocations() {
        return deepCopy(locations);
    }

    public synchronized MutablePoint getLocations(String id) {
        MutablePoint loc = locations.get(id);
        return loc == null ? null : new MutablePoint(loc);
    }

    public synchronized void setLocations(String id, int x, int y) throws IllegalAccessException {
        MutablePoint loc = locations.get(id);
        if (loc == null) {
            throw new IllegalAccessException("No such id : "+ id);
        }
        loc.x = x;
        loc.y = y;
    }

    /**
     * 如果车辆多，就有可能变得缓慢了，另外一个就是，虽然车辆的实际位置发生了变化，但是返回的信息却保持不变
     * 因为在拷贝过程中可能已经更新了某些车辆的位置信息，这种情况是好是坏，要取决于业务需求
     * @param m
     * @return
     */
    private static Map<String,MutablePoint> deepCopy(Map<String, MutablePoint> m) {
        Map<String, MutablePoint> result = new HashMap<>();
        for (String id : m.keySet()) {
            result.put(id,m.get(id));
        }
        return Collections.unmodifiableMap(result);
    }
}

class TestLocation {
    public static void main(String[] args) {

    }
}